package com.jiepos.mpos.pay;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.jiepos.mpos.common.constant.DBConstant.Table;
import com.jiepos.mpos.common.constant.RspCodeConstant;
import com.jiepos.mpos.common.constant.SystemConstant;
import com.jiepos.mpos.common.dao.AppCustomBankcardDao;
import com.jiepos.mpos.common.dao.AppLogTransJnlsDao;
import com.jiepos.mpos.common.dao.AppPayDao;
import com.jiepos.mpos.common.dao.CardBinDao;
import com.jiepos.mpos.common.dao.CustomAccountDao;
import com.jiepos.mpos.common.dao.LogClientKeyDao;
import com.jiepos.mpos.common.dao.TransLimitDao;
import com.jiepos.mpos.common.entity.App_Custom_BankcardEntity;
import com.jiepos.mpos.common.entity.GpsEntity;
import com.jiepos.mpos.common.service.AbrBaseHttpService;
import com.jiepos.mpos.core.service.BaseInterService;
import com.jiepos.mpos.core.util.DateUtil;
import com.jiepos.mpos.core.util.GlobalUtils;
import com.jiepos.mpos.core.util.HttpUtil;
import com.jiepos.mpos.core.util.IDFactoryUtil;
import com.jiepos.mpos.core.util.MathUtils;
import com.jiepos.mpos.core.util.RSACoder;
import com.jiepos.mpos.core.util.StringUtils;
import com.jiepos.mpos.core.util.Tool3DES;
import com.jiepos.mpos.inter.intopieces.dto.ResponseDTO;



/**
 * 
 * 主业务服务
 * 模块: 通用平台
 * 版权: Copyright (c) 2017 江苏杰博实信息技术有限公司
 * @author 杨剑武
 * @version 1.0
 * @since 2017年9月25日 下午15:11:00 
 * @history（历次修订内容、修订人、修订时间等）
 */
@Service
@SuppressWarnings("unchecked")
public class MainBusinessService extends AbrBaseHttpService {
	private static final Logger _log = LoggerFactory.getLogger(MainBusinessService.class);
	
	@Autowired
	private LogClientKeyDao logClientKeyDao;
	
	@Autowired
	private AppCustomBankcardDao appCustomBankcardDao;
	
	@Autowired
	private TransLimitDao transLimitDao;
	
	@Autowired
	private CustomAccountDao customAccountDao;
	
	@Autowired
	private CardBinDao cardBinDao;	
	
	@Autowired
	private AppPayDao appPayDao;
	
	@Autowired
	private AppLogTransJnlsDao appLogTransJnlsDao;
	
	@Autowired
	private BaseInterService baseInterService;
	
	
	/**
	 * 验证机构、会员限制
	 * @param map
	 * @return
	 */
	public boolean validateParamLimit(Map<String, String> payReqsMap) {
		_log.info("机构、会员限额服务请求参数为:[交易流水={},会员编号={},支付卡号={},交易金额={},业务机构UUID={},业务主键={},业务参数主键={},会员级别={},卡性质={}]",
				payReqsMap.get("loc_trace_no"), payReqsMap.get("custom_no"), payReqsMap.get("act_out_no"),
				payReqsMap.get("trans_at"), payReqsMap.get("service_ins_uuid"), payReqsMap.get("service_uuid"),
				payReqsMap.get("service_param_uuid"), payReqsMap.get("custom_level"), payReqsMap.get("crd_nature"));
		try {
			double amt = Double.valueOf(payReqsMap.get("trans_at"));
			Map<String,String> dataMap = appPayDao.getTranLimitResult(payReqsMap.get("loc_trace_no"), payReqsMap.get("custom_no"),
					payReqsMap.get("act_out_no"), amt, payReqsMap.get("service_ins_uuid"), payReqsMap.get("service_uuid"),
					payReqsMap.get("service_param_uuid"), payReqsMap.get("custom_level"), payReqsMap.get("crd_nature"));
			_log.info("会员、机构限额结果为:[{}]", dataMap);
			if (!StringUtils.isEmpty(dataMap) && "1".equals(dataMap.get("result"))) {
				return true;
			}else{
				payReqsMap.put(SystemConstant.RSP_MSG, dataMap.get("result_desc"));
			}
		} catch (Exception e) {
			_log.error("查询会员、机构限额发生异常!", e);
		}
		return false;
	}

	/**
	 * 验证会员对应机构的受理交易类型
	 * @param param
	 * @param service_no
	 * @return
	 * @throws SQLException 
	 */
	public boolean checkTranType(Map<String, String> payReqMap) throws SQLException {

		return appPayDao.getTranType(payReqMap.get("service_ins_uuid"), payReqMap.get("service_uuid"), payReqMap.get("service_param_uuid"),  payReqMap.get("custom_level"));
	}
	
	/**
	 * 校验必传项是否为空
	 * @param map
	 * @param checkMap
	 * @return
	 */
	public Map<String, String> checkNull(Map<String, String> checkMap){
		_log.info("校验必填项数据为=[{}]",checkMap);
		for(Map.Entry<String, String> entry : checkMap.entrySet()){
			if(StringUtils.isBlank(entry.getValue())){
				return getRspMap(RspCodeConstant.RSPCODE_300014, null, null);
			}            
        }
		return null;
	}

	
	/**
	 * 
	 * 功能描述:快捷支付客户端第一次上送的信息(服务端解密并保存)
	 * 
	 * @param crd_exp
	 * @param phone
	 * @param cvv2
	 */
	public boolean saveCardInfo(Map<String, String> payReqMap, String version) {
		_log.info("支付卡保存服务请求参数[map={},version={}]", payReqMap, version);
		try {
			App_Custom_BankcardEntity bankCardEntity = null;
			if (!appPayDao.getActUuid(payReqMap.get("act_out_no"))) {
				String crd_exp = payReqMap.get("crd_exp");
				String cvv2 = payReqMap.get("cvv2");
				if(!"gate".equals(payReqMap.get("inte_flag"))){
					Assert.notNull(payReqMap.get("random_number"));// 上送随机数
					Assert.notNull(crd_exp);// 有效期密文
					Assert.notNull(cvv2);// cvv2密文
					// 先得到数据明文
					String keyData = StringUtils.MD5(DateUtil.getCurrDateStr() + version);
					// 本地加密秘钥对数据明文加密得到加密秘钥
					String key1 = Tool3DES.trides_crypt(SystemConstant.LOC_KEY, keyData);
					// 用加密秘钥对密客户端随机数进行加密，得到token的加密秘钥
					String cryptStr = Tool3DES.trides_crypt(key1, payReqMap.get("random_number"));
					Map<String, Object> clientKey = appPayDao.getLogClientKey(cryptStr);
					if (StringUtils.isEmpty(clientKey)) {
						payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300057);
						return false;
					}
					Assert.notNull(clientKey.get("exp_dt_key"));
					Assert.notNull(clientKey.get("cvv2_key"));
					String[] crd_exp_keys = String.valueOf(clientKey.get("exp_dt_key")).split("##");
					String[] cvv2_keys = String.valueOf(clientKey.get("cvv2_key")).split("##");
					if (crd_exp_keys.length != 2 && cvv2_keys.length != 2) {
						_log.warn("随机数[{}],对应的有效期密文[{}],cvv2密文[{}]格式异常!", payReqMap.get("random_number"),
								clientKey.get("exp_dt_key"), clientKey.get("cvv2_key"));
						payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300058);
						return false;
					}
					String crd_exp_key = new String(RSACoder.decryptByPublicKey(RSACoder.decryptBASE64(crd_exp_keys[0]),
							SystemConstant.pay_pub_key));// 公钥解密
					crd_exp = new String(RSACoder.decryptByPrivateKey(
							RSACoder.decryptBASE64(crd_exp), crd_exp_key + crd_exp_keys[1]));
					String cvv2_key = new String(
							RSACoder.decryptByPublicKey(RSACoder.decryptBASE64(cvv2_keys[0]), SystemConstant.pay_pub_key));// 公钥解密
					cvv2 = new String(RSACoder.decryptByPrivateKey(RSACoder.decryptBASE64(cvv2),
							cvv2_key + cvv2_keys[1]));
				}
				bankCardEntity = new App_Custom_BankcardEntity();
				String bankcard_uuid = IDFactoryUtil.getUUID();
				bankCardEntity.setBankcard_uuid(bankcard_uuid);
				bankCardEntity.setCustom_uuid(payReqMap.get("custom_uuid"));
				bankCardEntity.setCrd_exp(crd_exp);
				bankCardEntity.setCvv2(cvv2);
				bankCardEntity.setPhone(payReqMap.get("phone"));
				bankCardEntity.setSettle_acct(payReqMap.get("act_out_no"));
				bankCardEntity.setAcct_nm(payReqMap.get("name"));// 姓名
				bankCardEntity.setCertificate_no(payReqMap.get("certificate_no"));// 身份证号
				bankCardEntity.setSuper_bank_no(payReqMap.get("super_bank_no"));
				bankCardEntity.setSuper_bank_nm(payReqMap.get("super_bank_name"));
				bankCardEntity.setAcct_attr(SystemConstant.ACCT_ATTR_1);//卡性质
				bankCardEntity.setAudit_st(SystemConstant.REVIEW_ST_1);//审核通过
				bankCardEntity.setRec_st(SystemConstant.READ_ST_1);
				bankCardEntity.setLast_oper_in("A");// 最后的操作标志为A
				bankCardEntity.setRec_upd_usr_id(payReqMap.get("login_id"));
				bankCardEntity.setRec_crt_ts(new Timestamp(System.currentTimeMillis()));
				bankCardEntity.setAuth_bank_card_st(SystemConstant.AUTH_BANK_CARD_ST_0);// 未认证信用卡
				appCustomBankcardDao.save(bankCardEntity);
				payReqMap.put("crd_exp", crd_exp);
				payReqMap.put("cvv2", cvv2);
				payReqMap.put("bankcard_uuid", bankcard_uuid);
				_log.info("会员[{}]支付账户[{}]保存成功!", payReqMap.get("custom_no"), payReqMap.get("act_out_no"));
				return true;
			} else {
				_log.warn("会员[{}]交易流水[{}]新增支付账户[{}]失败,此卡号已经存在!", payReqMap.get("custom_no"),
						payReqMap.get("loc_trace_no"), payReqMap.get("act_out_no"));
				payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300055);
			}
		} catch (Exception e) {
			payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300059);
			_log.error("支付卡保存发生异常", e);
		}
		return false;
	}

	/**
	 * 校验会员账户状态
	 * @param payReqMap
	 * @return
	 */
	public Map<String, String> checkAccountSt(Map<String, String> payReqMap){
		_log.info("校验会员账户状态请求的map=[{}]", payReqMap);
		try {
			StringBuffer sb = new StringBuffer();
			sb.append("select t1.account_uuid,t1.custom_uuid,t1.account_no,t1.account_st from ");		
			sb.append(Table.T_APP_CUSTOM_ACCOUNT);
			sb.append(" t1 inner join ");
			sb.append(Table.T_APP_CUSTOM_INF);
			sb.append(" t2 on t1.custom_uuid=t2.custom_uuid ");			
			sb.append(" where t1.rec_st!='0' and t2.custom_no = '");
			sb.append(payReqMap.get("custom_no"));
			sb.append("'");
			List<Map<String,String>> result=customAccountDao.queryForList(sb.toString());
			if(result.size()==0||result==null){
				return getRspMap(RspCodeConstant.RSPCODE_300015, null, null);
			}else{				
				if("1".equals(result.get(0).get("account_st"))){
					return new HashMap();
				}else{
					return getRspMap(RspCodeConstant.RSPCODE_300015, null, null);
				}
			}
		} catch (Exception e) {
			_log.error("校验会员账户状态发生异常", e);
			return getRspMap(RspCodeConstant.RSPCODE_300015, null, null);
		}		
	}
	
	
	/**
	 * 异步通知更新限额
	 * @param trans_date
	 * @param trans_amount
	 */
	public void updateLimitByNotice(String trans_date,String trans_amount,String trf_channel_id,String trf_mchnt_cd){				
		_log.info("异步通知更新限额trans_date="+trans_date+"trans_amount="+trans_amount+"trf_channel_id="+trf_channel_id+"trf_mchnt_cd="+trf_mchnt_cd);
		try {
			String today=DateUtil.getCurrDateStr();
			if(StringUtils.isBlank(trans_date)){
				trans_date="";
			}
			if(StringUtils.isBlank(trans_amount)){
				trans_amount="0";
			}
			if(StringUtils.isBlank(trf_channel_id)){
				trf_channel_id="";
			}
			if(StringUtils.isBlank(trf_mchnt_cd)){
				trf_mchnt_cd="";
			}
			StringBuilder sb = new StringBuilder();
			sb.append("update ");
			sb.append(Table.T_APP_TRANS_LIMIT);
			sb.append(" t1  set t1.trans_date= case when t1.trans_date='");
			sb.append(trans_date).append("'");
			sb.append(" then  t1.trans_date else '");
			sb.append(today).append("'");
			sb.append(" end,  t1.trans_amount=");
			sb.append(" case when t1.trans_date='");
			sb.append(trans_date).append("'");
			sb.append(" then  (nvl(t1.trans_amount ,0) +");
			sb.append(MathUtils.div(Double.parseDouble(trans_amount), Double.parseDouble("100"), 2));
			sb.append(") else  ");
			sb.append(MathUtils.div(Double.parseDouble(trans_amount), Double.parseDouble("100"), 2));
			sb.append(" end");
			sb.append(" where t1.rec_st!='");
			sb.append(SystemConstant.DEL_STATUS);
			sb.append("' and t1.limit_type='01' and t1.limit_idx='");
			sb.append(trf_channel_id+"'");
			/*List paramList=new ArrayList();
			paramList.add(trans_date);			
			paramList.add(today);	
			paramList.add(trans_date);	
			paramList.add(MathUtils.div(new Double(trans_amount), new Double(100), 2));	*/			
			transLimitDao.update(sb.toString());
			
			sb = new StringBuilder();
			sb.append("update ");
			sb.append(Table.T_APP_TRANS_LIMIT);
			sb.append(" t1  set t1.trans_date= case when t1.trans_date='");
			sb.append(trans_date).append("'");
			sb.append(" then  t1.trans_date else '");
			sb.append(today).append("'");
			sb.append(" end,  t1.trans_amount=");
			sb.append(" case when t1.trans_date='");
			sb.append(trans_date).append("'");
			sb.append(" then  (nvl(t1.trans_amount ,0) +");
			sb.append(MathUtils.div(Double.parseDouble(trans_amount), Double.parseDouble("100"), 2));
			sb.append(") else  ");
			sb.append(MathUtils.div(Double.parseDouble(trans_amount), Double.parseDouble("100"), 2));
			sb.append(" end");
			sb.append(" where t1.rec_st!='");
			sb.append(SystemConstant.DEL_STATUS);
			sb.append("' and t1.limit_type='02' and t1.limit_idx='");
			sb.append(trf_mchnt_cd+"'");
			/*List paramList=new ArrayList();
			paramList.add(trans_date);			
			paramList.add(today);	
			paramList.add(trans_date);	
			paramList.add(MathUtils.div(new Double(trans_amount), new Double(100), 2));	*/			
			transLimitDao.update(sb.toString());
		} catch (Exception e) {
			_log.error("异步通知更新限额发生异常", e);
		}
	}
	
	
	/**
	 * 新增客户端秘钥信息
	 * @param clientKey
	 * @param map
	 * @throws Exception 
	 */
	public Map<String,String> saveClientKey(Map<String,String> payReqMap,GpsEntity gpsEntity){
		_log.info("更新客户端秘钥信息map=[{}]", payReqMap);
		try {
			StringBuffer sb=new StringBuffer();
			sb.append("select random_number,custom_no,client_version,pin_key,cvv2_key,rand_key,exp_dt_key from");
			sb.append("(select random_number,custom_no,client_version,pin_key,cvv2_key,rand_key,exp_dt_key from ");
			sb.append(Table.T_APP_LOG_CLIENT_KEY);
			sb.append(" where rec_st='1' and custom_no='");
			sb.append(payReqMap.get("custom_no")).append("' order by rec_crt_ts desc ) where rownum=1 ");
			List<Map<String,String>> result=logClientKeyDao.queryForList(sb.toString());
			if(result!=null&&result.size()>0){
				Map<String,String> map=result.get(0);				
				//先得到数据明文
	            String keyData = StringUtils.MD5(DateUtil.getCurrDateStr() + gpsEntity.getVersion());	            
	            //本地加密秘钥对数据明文加密得到加密秘钥
	            String key1 = Tool3DES.trides_crypt(SystemConstant.LOC_KEY, keyData);	            
	            //用加密秘钥对密客户端随机数进行加密，得到token的加密秘钥
	            String cryptStr = Tool3DES.trides_crypt(key1, payReqMap.get("random_number"));		            
				if(cryptStr.toUpperCase().equals(map.get("random_number"))){					
					sb=new StringBuffer();
					sb.append("update ");
					sb.append(Table.T_APP_LOG_CLIENT_KEY);
					sb.append(" set pin_key=?,cvv2_key=?,rand_key=?,exp_dt_key=?,rec_upd_ts=?,last_oper_in=?");										
					sb.append(" where random_number=?");
					Map<String,String> pinKeyMap=getClientKeyMap();
					Map<String,String> cvv2KeyMap=getClientKeyMap();
					Map<String,String> randKeyMap=getClientKeyMap();
					Map<String,String> expDtKeyMap=getClientKeyMap();
					if(pinKeyMap==null||pinKeyMap.isEmpty()||cvv2KeyMap==null||cvv2KeyMap.isEmpty()
							||randKeyMap==null||randKeyMap.isEmpty()||expDtKeyMap==null||expDtKeyMap.isEmpty()){
						return getRspMap(RspCodeConstant.RSPCODE_300018, null, null);
					}
					
					List paramList = new ArrayList();												
					paramList.add(pinKeyMap.get("encryptPriKey"));
					paramList.add(cvv2KeyMap.get("encryptPriKey"));
					paramList.add(randKeyMap.get("encryptPriKey"));
					paramList.add(expDtKeyMap.get("encryptPriKey"));																				
					paramList.add(new Timestamp(System.currentTimeMillis()));					
					paramList.add(SystemConstant.OPER_UPDATE);
					paramList.add(cryptStr.toUpperCase());
					logClientKeyDao.update(sb.toString(), paramList);
					payReqMap.put("pin_key", pinKeyMap.get("encryptPubKey"));
					payReqMap.put("cvv2_key", cvv2KeyMap.get("encryptPubKey"));
					payReqMap.put("rand_key", randKeyMap.get("encryptPubKey"));
					payReqMap.put("exp_key", expDtKeyMap.get("encryptPubKey"));
					return new HashMap<String,String>();
				}else{
					return getRspMap(RspCodeConstant.RSPCODE_300031, null, null);
				}				
			}else{
				return getRspMap(RspCodeConstant.RSPCODE_300032, null, null);
			}									
		} catch (Exception e) {
			_log.error("更新客户端秘钥信息发生异常!", e);
			return getRspMap(RspCodeConstant.RSPCODE_300018, null, null);
		}
	}
	
	/**
	 * 获取加密密钥对
	 * @return
	 */
	public Map<String,String> getClientKeyMap(){
		try {
			Map<String,String> encryptKeyMap=new HashMap<String,String>();
			Map<String,Object> keyMap=RSACoder.initKey();
			String pubKey=RSACoder.getPublicKey(keyMap);
			String priKey=RSACoder.getPrivateKey(keyMap);
			String encryptPubKey=RSACoder.encryptBASE64(RSACoder.encryptByPrivateKey(pubKey.substring(0, 64).getBytes(), SystemConstant.pay_pri_key));
			String encryptPriKey=RSACoder.encryptBASE64(RSACoder.encryptByPrivateKey(priKey.substring(0, 64).getBytes(), SystemConstant.pay_pri_key));
			encryptKeyMap.put("encryptPubKey", encryptPubKey+"##"+pubKey.substring(64));
			encryptKeyMap.put("encryptPriKey", encryptPriKey+"##"+priKey.substring(64));
			return encryptKeyMap;
		} catch (Exception e) {			
			_log.error("加密密钥对发生异常!", e);
			return new HashMap<String,String>();
		}		
	}
	/**
	 * 
	 * 接口: 更新会员参数表
	 * @param payReqMap
	 * @since 2017年10月23日
	 */
	public void updateCustomServiceParam(Map<String, String> payReqMap) {
		_log.info("更新会员参数表为:[交易流水={},交易日期={},会员uuid={},业务机构uuid={},业务参数主键={},交易金额(单位:分)={}]", payReqMap.get("loc_trace_no"),
				payReqMap.get("complete_dt"), payReqMap.get("custom_uuid"), payReqMap.get("service_ins_uuid"),
				payReqMap.get("service_param_uuid"), payReqMap.get("trans_at"));
		try {
			if (!StringUtils.isBlank(payReqMap.get("loc_trace_no"))
					&& !StringUtils.isBlank(payReqMap.get("complete_dt"))
					&& !StringUtils.isBlank(payReqMap.get("custom_uuid"))
					&& !StringUtils.isBlank(payReqMap.get("service_ins_uuid"))
					&& !StringUtils.isBlank(payReqMap.get("service_param_uuid"))
					&& !StringUtils.isBlank(payReqMap.get("trans_at"))) {
				Double amt = MathUtils.div(Double.valueOf(payReqMap.get("trans_at")), 100);
				String result = appPayDao.updateCustomServiceParam(payReqMap.get("loc_trace_no"),
						payReqMap.get("complete_dt"), payReqMap.get("custom_uuid"), payReqMap.get("service_ins_uuid"),
						payReqMap.get("service_param_uuid"), amt);
				if ("1".equals(result)) {
					_log.info("会员参数更新成功!");
				}
			}
		} catch (Exception e) {
			_log.error("更新会员参数发生异常!", e);
		}
	}

	
	/**
	 * 
	 * 接口: 检查会员是否存在
	 * @param payReqMap
	 * @return
	 * @since 2017年10月21日
	 */
	public boolean checkCustomerInfo(Map<String, String> payReqMap) {
		try {
			Map<String, Object> data = appPayDao.getCustomInfo(payReqMap.get("custom_no"));
			_log.info("[{}]会员对应的基本会员信息[{}]", payReqMap.get("custom_no"), data);
			if (!StringUtils.isEmpty(data)) {
				payReqMap.put("custom_uuid", String.valueOf(data.get("custom_uuid")));// 会员UUID
				payReqMap.put("login_id", String.valueOf(data.get("login_id")));// 会员登录id
				payReqMap.put("user_st", String.valueOf(data.get("user_st")));// 会员状态
				payReqMap.put("name", String.valueOf(data.get("name")));// 会员姓名
				payReqMap.put("certificate_no", String.valueOf(data.get("certificate_no")));// 会员证件号码
				payReqMap.put("realname_auth_st", String.valueOf(data.get("realname_auth_st")));// 会员实名认证状态
				payReqMap.put("vip_st", String.valueOf(data.get("vip_st")));// 会员VIP认证状态
				payReqMap.put("pay_pass_word", String.valueOf(data.get("pay_pass_word")));//会员支付密码
				if (SystemConstant.USER_ENABLED.equals(data.get("user_st"))
						&& SystemConstant.AUTH_ST_1.equals(data.get("realname_auth_st"))) {
					payReqMap.put("custom_level", SystemConstant.CUSTOM_LEVEL_1);
					if ("1".equals(data.get("vip_st"))) {
						payReqMap.put("custom_level", SystemConstant.CUSTOM_LEVEL_2);
					}
					return true;
				}else if(SystemConstant.USER_DISABLED.equals(data.get("user_st"))){
					payReqMap.put(SystemConstant.RSP_MSG, "停用");
				}else if(SystemConstant.USER_LOCKED.equals(data.get("user_st"))){
					payReqMap.put(SystemConstant.RSP_MSG, "冻结");
				}else{
					payReqMap.put(SystemConstant.RSP_MSG, "未知");
				}
			}
		} catch (Exception e) {
			_log.error("根据会员编号查询会员信息", e);
		}
		return false;
	}
	
	/**
	 * 
	 * 接口: 检查会员状态
	 * @param payReqMap
	 * @return
	 * @since 2017年10月21日
	 */
	public boolean checkCustomerState(Map<String, String> payReqMap) {
		_log.info("[{}]会员对应的会员登记为[{}]", payReqMap.get("custom_no"), payReqMap.get("custom_level"));
		if (SystemConstant.CUSTOM_LEVEL_1.equals(payReqMap.get("custom_level"))
				|| SystemConstant.CUSTOM_LEVEL_2.equals(payReqMap.get("custom_level"))) {
			return true;
		} else {
			payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300004);
			return false;
		}
	}
	
	/**
	 * 
	 * 接口: 检查机构状态
	 * @param payReqMap
	 * @return
	 * @throws Exception 
	 * @since 2017年10月21日
	 */
	public boolean checkInsState(Map<String, String> payReqMap) throws Exception {
		_log.info("[{}]会员检查机构状态参数[本地流水号={},系统业务={},系统业务参数={},客户级别={}]", payReqMap.get("custom_no"),
				payReqMap.get("loc_trace_no"), payReqMap.get("service_uuid"), payReqMap.get("service_param_uuid"),
				payReqMap.get("custom_level"));
		Map<String, Object> dataMap = appPayDao.getCustomInsInfo(payReqMap.get("loc_trace_no"),
				payReqMap.get("custom_no"), payReqMap.get("service_uuid"), payReqMap.get("service_param_uuid"),
				payReqMap.get("custom_level"));
		if (!StringUtils.isEmpty(dataMap) && SystemConstant.INS_ST_1.equals(String.valueOf(dataMap.get("ins_st")))
				&& SystemConstant.INS_ST_1.equals(String.valueOf(dataMap.get("service_ins_st")))) {
			payReqMap.put("ins_uuid", String.valueOf(dataMap.get("ins_uuid")));// 会员合法机构
			payReqMap.put("service_ins_uuid", String.valueOf(dataMap.get("service_ins_uuid")));// 会员业务机构
			payReqMap.put("service_minfee", String.valueOf(dataMap.get("credit_minfee")));// 贷记卡最小手续费
			payReqMap.put("service_minfee", String.valueOf(dataMap.get("credit_minfee")));// 贷记卡最小手续费
			payReqMap.put("service_disc", String.valueOf(dataMap.get("credit_rate")));// 贷记卡扣率
			payReqMap.put("service_disc_maxfee", String.valueOf(dataMap.get("credit_maxfee")));// 贷记卡最大手续费
			payReqMap.put("service_attachfee", String.valueOf(dataMap.get("credit_attachfee")));// 贷记卡附加手续费
			_log.info("[{}]会员查询:合法机构查询结果[uuid={},ins_st={}],业务机构查询结果[uuid={},ins_st={}]", payReqMap.get("custom_no"),
					dataMap.get("ins_uuid"), dataMap.get("ins_st"), dataMap.get("service_ins_uuid"),
					dataMap.get("service_ins_st"));
			return true;
		} else {
			payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300005);
			return false;
		}
	}
	


	/**
	 * 
	 * 接口: 根据会员编号查询收款账号信息
	 * @param payReqMap
	 * @since 2017年10月23日
	 */
	public boolean getActInCardInfo(Map<String, String> payReqMap) {
		try {			
			if(SystemConstant.SERVICE_NO_100002.equals(payReqMap.get("service_no"))){
				Map<String, String> cardBinAttr = cardBinDao.getCardBinAttr(GlobalUtils.getPayConfProperty("act_in_no"));
				payReqMap.put("act_in_no", GlobalUtils.getPayConfProperty("act_in_no"));// 公司收款账户
				payReqMap.put("bank_nm", String.valueOf(cardBinAttr.get("super_bank_name")));// 开卡行名
				_log.warn("充值交易流水号[{}]公司收款账户信息[卡号={},开户行名={}]",payReqMap.get("loc_trace_no"),GlobalUtils.getPayConfProperty("act_in_no"),cardBinAttr.get("super_bank_name"));
				return true;
			}
			Map<String, Object> bankCardInfo = appPayDao.getCustomBankCardInfo(payReqMap.get("custom_uuid"));
			if (!StringUtils.isEmpty(bankCardInfo)) {
				_log.info("[{}]会员对应的收款账户信息[{}]",payReqMap.get("custom_no"),bankCardInfo);
				payReqMap.put("in_bankcard_uuid", String.valueOf(bankCardInfo.get("bankcard_uuid")));// 会员银行卡表主键
				payReqMap.put("act_in_no", String.valueOf(bankCardInfo.get("settle_acct")));// 收款账号(存储过程)
				payReqMap.put("acct_nm", String.valueOf(bankCardInfo.get("acct_nm")));// 账户名称
				payReqMap.put("bank_nm", String.valueOf(bankCardInfo.get("super_bank_nm")));// 开卡行名
				return true;
			}

		} catch (Exception e) {
			_log.error("查询会员对应银行卡信息发生异常！", e);
		}
		return false;
	}

	/**
	 * 接口: 根据卡号查询卡bin及卡性质
	 * @param payReqMap
	 * @return
	 * @since 2017年10月25日
	 */
	public boolean getCardBinAttrInfo(Map<String, String> payReqMap) {
		try {
			Map<String, String> cardBinAttr = cardBinDao.getCardBinAttr(payReqMap.get("act_out_no"));
			_log.info("卡号[{}]对应的卡信息[{}]", payReqMap.get("act_out_no"), cardBinAttr);
			if (StringUtils.isEmpty(cardBinAttr.get("card_bin"))
					|| StringUtils.isEmpty(cardBinAttr.get("crd_nature"))) {
				payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300006);
				return false;
			}
			if(!SystemConstant.CRD_NATURE_2.equals(String.valueOf(cardBinAttr.get("crd_nature")))){
				payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300019);
				return false;
			}
			payReqMap.put("card_bin", cardBinAttr.get("card_bin"));// 卡bin
			payReqMap.put("card_name", cardBinAttr.get("card_name"));
			payReqMap.put("card_ins_cd", cardBinAttr.get("card_ins_cd"));
			payReqMap.put("card_ins_nm", cardBinAttr.get("card_ins_nm"));
			payReqMap.put("crd_nature", cardBinAttr.get("crd_nature"));// 卡性质
			payReqMap.put("super_bank_no", cardBinAttr.get("super_bank_no"));
			payReqMap.put("super_bank_name", cardBinAttr.get("super_bank_name"));
			return true;
		} catch (Exception e) {
			_log.error("获取卡bin及卡性质信息发生异常", e);
			return false;
		}
	}

	/**
	 * 校验可用余额
	 * @param payReqMap
	 * @return
	 */
	public boolean checkAvailableAmt(Map<String, String> payReqMap) {
		_log.info("校验会员可用余额请求的map=[{}]", payReqMap);
		try {
			String custom_no = payReqMap.get("custom_no");
			String trans_at = payReqMap.get("trans_at");
			String acc_type = payReqMap.get("acc_type");
			StringBuffer sb = new StringBuffer();
			sb.append("select t1.custom_uuid,t1.account_type,t1.have_balance,balance from ");
			sb.append(Table.T_APP_CUSTOM_ACCOUNT);
			sb.append(" t1 inner join ");
			sb.append(Table.T_APP_CUSTOM_INF);
			sb.append(" t2 on t1.custom_uuid=t2.custom_uuid where t2.rec_st!='0' and t2.custom_no='");
			sb.append(custom_no).append("' and t1.account_type='");
			sb.append(acc_type).append("'");
			List<Map<String, String>> result = customAccountDao.queryForList(sb.toString());
			if (result.size() == 0 || result == null) {
				return false;
			} else {
				String have_balance = StringUtils.isBlank(String.valueOf(result.get(0).get("have_balance"))) ? "0"
						: String.valueOf(result.get(0).get("have_balance"));
				String balance = StringUtils.isBlank(String.valueOf(result.get(0).get("balance"))) ? "0"
						: String.valueOf(result.get(0).get("balance"));
				if (Double.valueOf(trans_at)
						.compareTo(MathUtils.mul(Double.parseDouble(have_balance), Double.parseDouble("100"))) > 0
						|| Double.valueOf(trans_at)
								.compareTo(MathUtils.mul(Double.parseDouble(balance), Double.parseDouble("100"))) > 0) {
					return false;
				} else {
					return true;
				}
			}
		} catch (Exception e) {
			_log.error("校验会员可用余额发生异常", e);
			return false;
		}

	}

	/**
	 * 接口: 校验系统业务
	 * @return
	 * @since 2017年10月25日
	 */
	public String getServiceUuid(String service_no) {
		try {
			Map<String, Object> dataMap = appPayDao.getServiceUuid(service_no);
			if (!StringUtils.isEmpty(dataMap)) {
				if (SystemConstant.INS_ST_1.equals(dataMap.get("service_st"))) {
					return String.valueOf(dataMap.get("service_uuid"));
				} else {
					return SystemConstant.INS_ST_0;
				}
			}
		} catch (Exception e) {
			_log.error("根据系统业务编号查询业务主键发生异常", e);
		}
		return null;
	}

	/**
	 * 
	 * 接口: 根据业务编号、业务主键查询业务参数主键
	 * @return
	 * @since 2017年10月25日
	 */
	public String getServiceParamUuid(String param_no, String service_uuid) {
		try {
			Map<String, Object> dataMap = appPayDao.getServiceParamUuid(param_no, service_uuid);
			if (!StringUtils.isEmpty(dataMap)) {
				if (SystemConstant.INS_ST_1.equals(dataMap.get("param_st"))) {
					return String.valueOf(dataMap.get("service_param_uuid"));
				} else {
					return SystemConstant.INS_ST_0;
				}
			}
		} catch (Exception e) {
			_log.error("根据业务参数编号及业务主键查询业务参数主键发生异常", e);
		}
		return null;
	}

	public String getActOutNo(Map<String, String> payReqMap) {
		try {
			Map<String, Object> dataMap = appPayDao.getActOutNo(payReqMap.get("bankcard_uuid"),payReqMap.get("act_out_no"));
			if (!StringUtils.isEmpty(dataMap)) {
				payReqMap.put("bankcard_uuid", String.valueOf(dataMap.get("bankcard_uuid")));// 查询对应的卡号
				payReqMap.put("name", String.valueOf(dataMap.get("acct_nm")));// 查询对应的卡号
				payReqMap.put("act_out_no", String.valueOf(dataMap.get("settle_acct")));// 查询对应的卡号
				payReqMap.put("crd_exp", String.valueOf(dataMap.get("crd_exp")));// 有效期
				payReqMap.put("cvv2", String.valueOf(dataMap.get("cvv2")));// cvv2
				payReqMap.put("phone", String.valueOf(dataMap.get("phone")));// 银行预留手机号
				return String.valueOf(dataMap.get("settle_acct"));
			}
		} catch (Exception e) {
			_log.error("根据银行卡uuid查询对应银行卡发生异常", e);
		}
		return null;
	}
	
	/**
	 * 根据流水号查询渠道对应的主密钥
	 * @param loc_trace_no
	 * @return
	 */
	public Map<String,String> getMasterKeyByLocTraceNo(String loc_trace_no){
		StringBuffer sb=new StringBuffer();
		sb.append("select t1.channel_no,t1.chn_nm,t1.chn_tp,t1.chn_prmtb,t2.trf_channel_id,t2.trf_mchnt_cd from ");
		sb.append(Table.T_APP_INF_CHANNEL);
		sb.append(" t1 inner join ");
		sb.append(Table.T_APP_LOG_TRANS_JNLS);
		sb.append(" t2 on t2.trf_channel_id=t1.channel_no where t1.rec_st!='0' and t2.loc_trace_no='");
		sb.append(loc_trace_no).append("'");
		List<Map<String,String>> result1 =logClientKeyDao.queryForList(sb.toString());
		if(result1==null||result1.size()==0){
			return getRspMap(RspCodeConstant.RSPCODE_300034, null, null);
		}
		String tableName=String.valueOf(result1.get(0).get("chn_prmtb"));
		String trf_mchnt_cd=String.valueOf(result1.get(0).get("trf_mchnt_cd"));
		if(StringUtils.isBlank(tableName)||StringUtils.isBlank(trf_mchnt_cd)){
			return getRspMap(RspCodeConstant.RSPCODE_300034, null, null);
		}
		sb=new StringBuffer();
		sb.append("select trf_mchnt_cd,master_key from ");
		sb.append(tableName);
		sb.append(" where rec_st!='0' and trf_mchnt_cd='");
		sb.append(trf_mchnt_cd).append("'");
		List<Map<String,String>> result2 =logClientKeyDao.queryForList(sb.toString());
		if(result2==null||result2.size()==0){
			return getRspMap(RspCodeConstant.RSPCODE_300034, null, null);
		}
		
		return result2.get(0);
	}
	
	/**
	 * 更新会员vip
	 * @param map
	 */
	public void updateCustomVipSt(Map<String,String> map){
		try{						
			//充值成功之后，会员升级为VIP			
			appPayDao.updateCustomVipSt(map.get("custom_uuid"));
			
		}catch(Exception e){			
			_log.error("vip更新发生异常",e);				
		}
	}
	
	/**
	 * 校验提现参数
	 * @param map
	 * @return
	 */
	public Map checkWithdraw(Map<String,String> map){
		_log.info("校验提现参数请求的map=[{}]", map);
		try{
			return appPayDao.checkWithdraw(map.get("login_id"), map.get("custom_uuid"), map.get("custom_level"), 
					map.get("service_uuid"), map.get("service_param_uuid"), 
					MathUtils.div(Double.parseDouble(String.valueOf(map.get("trans_at"))), Double.parseDouble("100"), 2),map.get("apply_no"));
		}catch(Exception e){
			_log.error("校验提现参数发生异常",e);	
			Map result=new HashMap();
			result.put("rsp_code", SystemConstant.RSPCODE_ERROR);
			result.put("rsp_msg", SystemConstant.RSPCODE_ERROR_MSG);
			return result;
		}
		
	}
	
	/**
	 * 
	 * 接口: 解密验证码及支付密码
	 * @return
	 * @author 杨剑武
	 * @since 2017年12月5日
	 */
	public boolean verifyData(Map<String, String> payReqMap, String version, String pay_pass_word) {
		_log.info("解密验证码请求参数[payReqMap={},version={},pay_pass_word={}]", payReqMap, version, pay_pass_word);
		try {
			Assert.notNull(payReqMap.get("random_number"));// 上送随机数
			Assert.notNull(payReqMap.get("verify_code"));// 验证码密文
			// 先得到数据明文
			String keyData = StringUtils.MD5(DateUtil.getCurrDateStr() + version);
			// 本地加密秘钥对数据明文加密得到加密秘钥
			String key1 = Tool3DES.trides_crypt(SystemConstant.LOC_KEY, keyData);
			// 用加密秘钥对密客户端随机数进行加密，得到token的加密秘钥
			String cryptStr = Tool3DES.trides_crypt(key1, payReqMap.get("random_number"));
			Map<String, Object> clientKey = appPayDao.getLogClientKey(cryptStr);
			if (StringUtils.isEmpty(clientKey)) {
				payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300057);
				return false;
			}
			Assert.notNull(clientKey.get("pin_key"));
			Assert.notNull(clientKey.get("rand_key"));
			String[] pin_keys = String.valueOf(clientKey.get("pin_key")).split("##");
			String[] rand_keys = String.valueOf(clientKey.get("rand_key")).split("##");
			if (pin_keys.length != 2 && rand_keys.length != 2) {
				_log.warn("[{}]随机数中密钥[pin_key={},rand_key={}]格式异常!", payReqMap.get("random_number"),
						clientKey.get("pin_key"), clientKey.get("rand_key"));
				payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300058);
				return false;
			}
			String pin_key = new String(
					RSACoder.decryptByPublicKey(RSACoder.decryptBASE64(pin_keys[0]), SystemConstant.pay_pub_key));// 公钥解密
			String pin = new String(
					RSACoder.decryptByPrivateKey(RSACoder.decryptBASE64(pay_pass_word), pin_key + pin_keys[1]));
			String rand_key = new String(
					RSACoder.decryptByPublicKey(RSACoder.decryptBASE64(rand_keys[0]), SystemConstant.pay_pub_key));// 公钥解密
			String verify_code = new String(RSACoder.decryptByPrivateKey(
					RSACoder.decryptBASE64(payReqMap.get("verify_code")), rand_key + rand_keys[1]));
			_log.info("解密服务:[pin={},verify_code={},加密后的密码={},支付密码={}]", pin, verify_code,
					StringUtils.MD5(payReqMap.get("custom_no") + pin), payReqMap.get("pay_pass_word"));
			payReqMap.put("verify_code", verify_code);
			payReqMap.put("decrypt_pay_pass_word", StringUtils.MD5(payReqMap.get("custom_no") + pin));//解密后的密码进行MD5
			return true;
		} catch (Exception e) {
			payReqMap.put(SystemConstant.RSP_CODE, RspCodeConstant.RSPCODE_300061);
			_log.error("解密验证码及支付密码发生异常", e);
			return false;
		}
	}
	
	public Map<String, Object> getSystemTime() throws Exception{
		return appPayDao.getSystemTime();
	}
	
	@Async
	public void asyncNotifyMpos(String loc_trace_no) throws Exception{
		NameValuePair[] data = { 
				new NameValuePair("locTransNo",loc_trace_no)
			};
		String prefixUrl = GlobalUtils.getPayConfProperty("mpos.prefixUrl");
		if(prefixUrl.startsWith("http")){
			HttpUtil.getHttpClientData(prefixUrl + "/transmonitor/show.do", data);
		}else if(prefixUrl.startsWith("https")){
			HttpUtil.getHttpClientSslData(prefixUrl + "/transmonitor/show.do", data);
		}
	}
	
	@Async
	public void asyncNotifyDto(String dto_bg_url, String loc_trace_no, String loc_dt, ResponseDTO responseDto) throws Exception{
		String result = "";
		StringBuffer sqlSb = new StringBuffer("update T_APP_LOG_TRANS_JNLS set ");
		Map<String, String> params = new HashMap<String, String>();
		Map<String, String> values = new HashMap<String, String>();
		params.put("loc_trace_no", loc_trace_no);
		params.put("loc_dt", loc_dt);
		
		NameValuePair[] data = { 
				new NameValuePair("rsp_code",responseDto.getRsp_code()),
				new NameValuePair("rsp_msg",responseDto.getRsp_msg()),
				new NameValuePair("data",responseDto.getData())
			};
		if(dto_bg_url.startsWith("http")){
			result = HttpUtil.getHttpClientData(dto_bg_url, data);
		}else if(dto_bg_url.startsWith("https")){
			result = HttpUtil.getHttpClientSslData(dto_bg_url, data);
		}
		if("success".equals(result.trim())){
			values.put("dto_asyc_rsp_code", SystemConstant.RSPCODE_SUCCESS);
		}else{
			values.put("dto_asyc_rsp_code", SystemConstant.RSPCODE_ERROR);
		}
		sqlSb.append("where loc_trace_no'" + loc_trace_no +"'");
		appLogTransJnlsDao.update(params, values);
	}
	
	/**
	 * 异步通知服务
	 * @param reqMap
	 * @throws Exception
	 */
	public void msgNotify(Map<String, String> reqMap) throws Exception{
		Map<String, String> standardDataMap=transferNoticeMap(reqMap);
		String respData = baseInterService.getResponseBizContent(null, standardDataMap);
		ResponseDTO dtoEntity=new ResponseDTO();
		dtoEntity.setData(respData);
		asyncNotifyDto(reqMap.get("dto_bg_url"),reqMap.get("loc_trace_no"),reqMap.get("loc_dt"),dtoEntity);		
	}
	
	/**
	 * 转换异步通知报文
	 * @param reqMap
	 * @return
	 */
	public Map<String, String> transferNoticeMap(Map<String, String> reqMap){
		Map<String, String> standardDataMap = new HashMap<String, String>();
		standardDataMap.put("order_no", reqMap.get("order_no"));// 订单号
		standardDataMap.put("channel_trace_no", reqMap.get("loc_trace_no"));// 渠道流水号
		standardDataMap.put("trans_at", reqMap.get("trans_at"));// 订单金额
		standardDataMap.put("midfee", reqMap.get("midfee"));// 商户手续费
		standardDataMap.put("costfee", reqMap.get("costfee"));// 成本手续费
		standardDataMap.put("mchnt_cd", reqMap.get("custom_no"));// 商户号
		standardDataMap.put("pay_success_time", reqMap.get("complete_dt")+reqMap.get("complete_ts"));// 支付成功时间
		standardDataMap.put("trs_stat", reqMap.get("trs_stat"));// 订单状态
		standardDataMap.put("stl_st", SystemConstant.AUDIT_STL_1);// 清算状态
		standardDataMap.put("stl_dt", StringUtils.isBlank(reqMap.get("stl_dt"))?reqMap.get("complete_dt"):reqMap.get("stl_dt"));// 清算日期
		standardDataMap.put("stl_time", StringUtils.isBlank(reqMap.get("pay_ts"))?reqMap.get("complete_ts"):reqMap.get("pay_ts"));// 清算时间		
		return standardDataMap;
	}
	
}
